module CanCamel::Validators
  ValidationError = Class.new(StandardError)
  UnknownFilter = Class.new(ValidationError)

  extend ActiveSupport::Autoload
  SUBMODULES = %i(GeneralValidators PathValidators)
  SUBMODULES.each { |x| autoload x }
  autoload :ValidatorsHelper
  SUBMODULES.each { |x| extend const_get(x) }

  class <<self
    def included(base)
      base.define_singleton_method(:validates) { |*args| CanCamel::Validators.validates *args }
    end

    def validates(filter, field = nil, **args)
      validators[filter] ||= []
      args.each do |key, value|
        validator =
          if field
            -> (x) { send(key, field: x[field], **value) }
          else
            -> (x) { send(key, args: x, **value) }
          end
        validators[filter].push(validator)
      end
    end

    def validate!(filter:, args:, path: nil)
      filter = filter.to_sym
      unless validators[filter]
        raise UnknownFilter unless CanCamel::Filter.filters.include? filter
        return
      end
      validators[filter].each { |x| x.call(path: path, **args) }
    end

    private

    def validators
      @validators ||= {}
    end
  end
end
